#include "AsyncLogHelper.h"

#include "utility/assertion.h"
#include "utility/chrono.h"

#include <array>
#include <cstring>

AsyncLogHelper::AsyncLogHelper(
    std::size_t rollSize, const std::string &prefix,
    const std::string &suffix, bool rename) :
    file{rollSize, prefix, suffix, rename, false},
    reservedBuffers{},
    buffers{} {
    for (auto &x : reservedBuffers) {
        x = std::make_unique<AsyncLog::Buffer>();
        x->bzero();
    }
    buffers.reserve(AsyncLog::RESERVED_SIZE);
}

void AsyncLogHelper::after_append() {
    if (buffers.size() > 2) {
        buffers.resize(2);
    }
    for (auto &x : reservedBuffers) {
        if (x) {
            continue;
        }
        assert(!buffers.empty());
        x = std::move(buffers.back());
        buffers.pop_back();
        x->clear();
    }
    buffers.clear();
    file.flush();
}

void AsyncLogHelper::append_too_much() {
    std::array<char, 1 << 8 > buffer{};
    ::snprintf(
        buffer.data(), buffer.size(), "Dropped log at %s, %zd, larger buffers\n",
        Utility::to_formatted_string(Utility::now()).c_str(), buffer.size() - 2);
    ::fputs(buffer.data(), stderr);
    file.append(buffer.data(), ::strlen(buffer.data()));
    buffers.erase(buffers.cbegin() + 2, buffers.cend());
}
